DevOps Blog - Nicolas Paris

X-Forwarded-For with Istio, Kubernetes and GCP load balancer

DevOpsIstioKubernetes

What I want: X-Forwarded-For HTTP Header in a Laravel application. In other words, the remote IP of the client.

What is my setup.

I had some trouble to find the correct information, here is a quick post to say it works for me, here how.

I have seen two main solution, the second works for me.

xff_num_trusted_hops

based on a blog post by Blablacar on medium

The idea is to trust hops before by changing the configuration of Envoy with the following.

I hopped that with the use_remote_address: true would help me, but it wasn't enought in my case.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: ingressgateway-settings
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: envoy.http_connection_manager
patch:
operation: MERGE
value:
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
use_remote_address: true
xff_num_trusted_hops: 2
workloadSelector:
labels:
istio: ingressgateway

It did changes the IP from the X-Forwarded-For header, but only from a local perspective. It did not get me the Client IP.

I found some alternative to this idea.

Here is a configuration of the Gateway Topology.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
defaultConfig:
gatewayTopology:
numTrustedProxies: 2

ExternalTrafficPolicy

The solution was found on istio documentation (the Network Loadbalancer tab)

What works for me was to set the externalTrafficPolicy to Local in the Istio Ingress Gateway.

kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec":{"externalTrafficPolicy":"Local"}}'

Once this patch, I did get the correct Client IP.